package com.smart.mac.utls;
  
import com.smart.mac.model.vo.UserDemoVO;
import com.google.common.cache.*;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
  
/**
 * 功能描述
 *
 */
@Slf4j
public class CacheManagerUtils {
  
  /** 缓存项最大数量 */
  private static final long GUAVA_CACHE_SIZE = 100;
  
  /** 缓存时间：天 */
  private static final long GUAVA_CACHE_DAY = 1;
  
  /** 缓存操作对象 */
  private static LoadingCache<String, UserDemoVO> GLOBAL_CACHE = null;
  
  static {
    try {
      GLOBAL_CACHE = loadCache(new CacheLoader<String, UserDemoVO>() {
        @Override
        public UserDemoVO load(String key) throws Exception {
          // 处理缓存键不存在缓存值时的处理逻辑
          return null;
        }
      });
    } catch (Exception e) {
      log.error("初始化Guava Cache出错", e);
    }
  }
  
  /**
   * 全局缓存设置
   *
   *
   * @param cacheLoader
   * @return
   * @throws Exception
   */
  private static  LoadingCache<String, UserDemoVO> loadCache(CacheLoader<String, UserDemoVO> cacheLoader) throws Exception {
     LoadingCache<String, UserDemoVO> cache = CacheBuilder.newBuilder()
        //缓存池大小，在缓存项接近该大小时， Guava开始回收旧的缓存项
        .maximumSize(GUAVA_CACHE_SIZE)
        //设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
        .expireAfterAccess(GUAVA_CACHE_DAY, TimeUnit.DAYS)
        // 设置缓存在写入之后 设定时间 后失效
        .expireAfterWrite(GUAVA_CACHE_DAY, TimeUnit.DAYS)
        //移除监听器,缓存项被移除时会触发
        .removalListener(new RemovalListener<String, UserDemoVO>() {
          @Override
          public void onRemoval(RemovalNotification<String, UserDemoVO> rn) {
            //逻辑操作
          }
        })
        //开启Guava Cache的统计功能
        .recordStats()
        .build(cacheLoader);
    return cache;
  }
  
  /**
   * 设置缓存值
   * 注: 若已有该key值，则会先移除(会触发removalListener移除监听器)，再添加
   *
   * @param key
   * @param value
   */
  public static void put(String key, UserDemoVO value) {
    try {
      GLOBAL_CACHE.put(key, value);
    } catch (Exception e) {
      log.error("设置缓存值出错", e);
    }
  }
  
  /**
   * 获取缓存值
   * 注：如果键不存在值，将调用CacheLoader的load方法加载新值到该键中
   *
   * @param key
   * @return
   */
  public static UserDemoVO get(String key) {
    UserDemoVO demoVO = null;
    try {
      demoVO = GLOBAL_CACHE.get(key);
    } catch (Exception e) {
      log.error("获取缓存值出错", e);
    }
    return demoVO;
  }
  
  /**
   * 移除缓存
   *
   * @param key
   */
  public static void remove(String key) {
    try {
      GLOBAL_CACHE.invalidate(key);
    } catch (Exception e) {
      log.error("移除缓存出错", e);
    }
  }
  
  /**
   * 获取缓存项数量
   *
   * @return
   */
  public static long size() {
    long size = 0;
    try {
      size = GLOBAL_CACHE.size();
    } catch (Exception e) {
      log.error("获取缓存项数量出错", e);
    }
    return size;
  }
}